#ifndef __TIMERMANAGER_H__
#define __TIMERMANAGER_H__
#include "../../include/timer_interface.hpp"
#include "list.h"
#include "../../include/objpool.hpp"

#define TVN_BITS 6
#define TVR_BITS 8
#define TVN_SIZE (1 << TVN_BITS)
#define TVR_SIZE (1 << TVR_BITS)
#define TVN_MASK (TVN_SIZE - 1)
#define TVR_MASK (TVR_SIZE - 1)

typedef struct tvec 
{
	struct list_head vec[TVN_SIZE];
}TVec;

typedef struct tvec_root 
{
	struct list_head vec[TVR_SIZE];
}TVec_Root;

typedef struct timer_list 
{
	struct list_head entry;
	UINT32 dwExpires;
	INT32 iElapse;
	INT32 iCount;
	void* pData;
}STimerInfo;

class CTimerManager :
    public ITimerManager
{
public:
    CTimerManager(void);
    virtual ~CTimerManager(void);

public:
    bool Init(ITimerResponse* poTimerResponse, bool bExact = false);
    void UnInit(void);
    virtual HTIMER AddTimer(INT32 iElapse, INT32 iCount, void* pData=NULL);
    virtual bool ModTimer(HTIMER hTimer, INT32 iElapse, INT32 iCount, void* pData=NULL);
    virtual void DelTimer(HTIMER hTimer);
    virtual INT32 GetCount(HTIMER hTimer);
    virtual bool Update(UINT32 dwRunTime);
    virtual void Release(void);
    virtual void* GetData(HTIMER hTimer);
protected:
    bool __ExactUpdate(void);
    bool __NormalUpdate(UINT32 run_time);
    STimerInfo* __GetTimerInfoByEntry(list_head* head);

    void __AddTimer(STimerInfo& rTimerInfo);
    bool __TimerPending(STimerInfo& rTimerInfo);
    void __DetachTimer(STimerInfo& rTimerInfo, bool bClearPending);

	INT32 __Cascade(TVec* tv, INT32 index);
    inline STimerInfo* __Handle2Info(HTIMER handle)
    {
        STimerInfo* pstTimerInfo = (STimerInfo*)handle;
        if (!pstTimerInfo || !m_pool_timer_info.IsAllocByPool(pstTimerInfo))
        {
            return NULL;
        }

        return pstTimerInfo;
    }
protected:
    UINT32      m_dwLastTick;
    bool        m_is_exact;

    CObjPool<STimerInfo>    m_pool_timer_info;
	TVec_Root	            m_tv1;
	TVec		            m_tv2;
	TVec		            m_tv3;
	TVec		            m_tv4;
	TVec		            m_tv5;

	ITimerResponse* m_poTimerResponse;
};
#endif
